home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / findcmd.cq / findcmd.c
Encoding:
C/C++ Source or Header  |  1985-06-03  |  13.5 KB  |  576 lines

  1. /* findcmd - a unix-like program/file finder for MS-DOS 2.x
  2.  *
  3.  * Bell Communications Research, 1985
  4.  * by Vincent Hatem
  5.  * Raritan River Software Systems Center
  6.  * 444 Hoes Lane
  7.  * RRC 4D-360
  8.  * Piscataway, NJ 08854
  9.  *
  10.  */
  11.  
  12. #include <stdio.h>
  13. #define CIC86
  14.  
  15. /* customizing constants */
  16.  
  17. #define QS       '\\'                 /* filename separator character */
  18. #define DQS       "\\"                 /* filename separator (string) */
  19. #define ID    0            /* always identify directory if 1 */
  20. #define ALL    0            /* show hidden files by default if 1 */
  21. #define LONG    0            /* long listing by default if 1 */
  22. #define COLM    0            /* 1-column listing by default if 1 */
  23. #define RSORT    0            /* reverse sort by default if 1 */
  24. #define TSORT    0            /* time sort by default if 1 */
  25. #define DU    0            /* include disk use by default if 1 */
  26.  
  27.  
  28. #define NAMESIZ 13            /* 12 character name + NULL */
  29. #define ONECS 512            /* cluster size on one-sided floppy */
  30. #define TWOCS 1024            /* cluster size on two-sided floppy */
  31. #define HARDCS 4096            /* cluster size on hard disk */
  32. #define SCRSIZ 23            /* scrolling size of display screen */
  33.  
  34. struct dta                /* DOS Disk Transfer Address table */
  35.     {
  36.     char reserved[21];        /* used in "find next" operation */
  37.     char attr;                /* file attribute byte */
  38.     int ftime;                /* time of last modification */
  39.     int fdate;                /* date of last modification */
  40.     long fsize;                /* file size in bytes */
  41.     char fname[NAMESIZ];            /* filename and extension */
  42.     };
  43.  
  44. struct outbuf                /* output buffer -- array of file structs */
  45.     {
  46.     unsigned oattr;
  47.     unsigned odate;
  48.     unsigned otime;
  49.     long osize;
  50.     char oname[NAMESIZ+1];
  51.     } *obuf;
  52.  
  53. char spath[80];             /* holds current pathname string */
  54.  
  55. /* global variables and flags */
  56.  
  57. int allf = ALL;             /* include hidden & system files */
  58. int ll = LONG;                /* long listing */
  59. int colm = COLM;            /* 1-column format */
  60. int rev = RSORT;            /* reverse sort */
  61. int tsrt = TSORT;            /* timesort the listing */
  62. int usage = DU;             /* print disk usage */
  63. int recd;                /* recursive descent requested */
  64. int sizonly;                /* only print sizes */
  65. int srclen;                /* length of the search string */
  66. int totcnt=0;                /* total # of entries found */
  67. int lstall=0;                /* list all directories traversed?? */
  68. char srcname[15];            /* name to search for */
  69.  
  70. int np;                 /* number of groups printed */
  71. int nargs;                /* number of non-option arguments */
  72. int clsize = 0;             /* size of a cluster, in bytes */
  73. int clmask;                /* clsize-1 for rounding & chopping */
  74. int drive;                /* code number for drive requested */
  75. int tsc;                /* 1 if output is to console screen */
  76. long left;                /* unused space left on disk */
  77. long total;                /* total of sizes encountered */
  78.  
  79. main(argc, argv)
  80. int argc;
  81. char *argv[];
  82. {
  83. char *s,*p;
  84. int c = 0;
  85. int nt = 0;
  86.  
  87. recd=1;
  88.  
  89. nargs = argc;
  90. tsc = toscreen();          /* find out if output is to console screen */
  91. obuf = (struct outbuf *)malloc(sizeof(*obuf));    /* point to free memory */
  92. if((*++argv)[0] == '-')
  93.     {
  94.     s= argv[0]+1;
  95.     if(*s == 'a')
  96.         {
  97.         lstall= 1;
  98.         argv++;
  99.         }
  100.        else
  101.         {
  102.         fprintf(stdout,"bad argument %s\n",argv);
  103.         exit(0);
  104.         }
  105.     }
  106.  
  107. if(argv[0] == '\0') {
  108.     fprintf(stdout,"useage:\n   findcmd [-a] filename\n");
  109.     exit(0);
  110.     }
  111. strcpy(srcname,*argv);            /* save name to look for */
  112. if ((p=strchr(srcname,'.')) == NULL)
  113.     strcat(srcname,".*");
  114. srclen= strlen(srcname);
  115.  
  116. curdrv(spath);                /* default to current drive */
  117. strcat(spath,DQS);        /* start at root */
  118. search(spath);            /* go do the hard work */
  119. if(totcnt)
  120.     fprintf(stdout,"%d entries found.\n",totcnt);
  121.    else
  122.     fprintf(stdout,"no entries found matching string \"%s\"\n",srcname);
  123. exit(0);
  124. }
  125.  
  126. getsize(path)                    /* get file cluster size */
  127. char *path;
  128. {
  129. if(clsize == 0)                 /* if size not already set */
  130.     if((clsize = getcl(path)) == 0) {    /* get cluster size for drive */
  131.         fprintf(stderr,
  132.          "Invalid drive: %c\n", *path);
  133.         return(1);
  134.         }
  135. clmask = clsize-1;
  136. return(0);
  137. }
  138.  
  139. /* toscreen - find out if output is to console screen */
  140.  
  141. toscreen()
  142. {
  143. struct { unsigned int ax, bx, cx, dx, si, di, ds, es;
  144.        } r;
  145.  
  146. r.ax = 0x4400;
  147. r.bx = 1;
  148. sysint(0x21, &r, &r);
  149. return(r.dx & 1);
  150. }
  151.  
  152. /* search - search 'path' for filename or directory */
  153.  
  154. search(path)
  155. char *path;
  156. {
  157. struct dta dta;                 /* DOS file data table */
  158. extern struct outbuf;                /* array of file structs */
  159. extern int nargs;                /* number of files or directories */
  160. int path_len;                    /* length of initial path */
  161. int z;                        /* char counter */
  162. int k = 0;                    /* counts number of entries found */
  163. char work[80];                    /* working path string */
  164. int comp();                    /* string, time comparison routine */
  165. int mask = 0x0010;                /* attribute mask */
  166. long bytes = 0;                 /* count of disk usage this directory */
  167.  
  168. if(allf)
  169.     mask = 0x001F;
  170. strcpy(work,path);
  171. path_len = strlen(work);            /* save original path length */
  172.  
  173. if(!find_first(work, &dta, 0) || work[path_len-1] == QS) {
  174.     if(work[path_len-1] != QS) {
  175.         strcat(work, DQS);        /* if path is to a directory */
  176.         path_len++;
  177.         }
  178.     strcat(work,srcname);            /* list everything in it */
  179.     }
  180.  
  181. if(find_first(work, &dta, mask)) {
  182.     do {
  183.         obuf[k].oattr = dta.attr;    /* stash this entry */
  184.         obuf[k].otime = dta.ftime;
  185.         obuf[k].odate = dta.fdate;
  186.         obuf[k].osize = dta.fsize;
  187.         strcpy(obuf[k].oname, dta.fname);
  188.  
  189.         if(usage || sizonly) {
  190.             if((dta.attr & 0x10) && dta.fname[0] != '.') {
  191.                 bytes += clsize;                /* sum up disk usage */
  192.                 }
  193.             else if(dta.fsize) {
  194.                 obuf[k].osize = ((dta.fsize + clmask) & (long)(~clmask));
  195.                 bytes += obuf[k].osize;
  196.                 }
  197.             }
  198.  
  199.         k++;
  200.         } while(find_next(&dta));
  201.     }
  202.  
  203. work[path_len] = NULL;                /* restore directory pathname */
  204. if((lstall == 1) || k)
  205.     {
  206.     fprintf(stdout, "%s", work);            /* identify the block */
  207.     fputc(endlin(),stdout);
  208.     }
  209. if(k > 0) {
  210.     longlist(k);                   /* list all entries */
  211.     fputc(endlin(),stdout);                         /* separate listing blocks */
  212.       }
  213. totcnt += k;
  214. strcat(work, "*.*");
  215. if(find_first(work, &dta, mask))        /* else find all sub-dirs */
  216.     do    {
  217.         if(dta.attr & 0x10 && dta.fname[0] != '.') {
  218.             work[path_len] = 0;                        /* discard old name */
  219.             for(z=0; dta.fname[z] != NULL; z++)
  220.                 dta.fname[z] = tolower(dta.fname[z]);
  221.             strcat(work, dta.fname);                /* install a new one */
  222.             strcat(work, DQS);
  223.             search(work);                            /* and recurse */
  224.             }
  225.     } while(find_next(&dta));
  226. return;
  227. }
  228.  
  229. /* find_first - find first file in chosen directory */
  230.  
  231. find_first(path, dta, mask)
  232. char *path;
  233. struct dta *dta;
  234. int mask;
  235. {
  236. struct { int ax, bx, cx;
  237.      char *dx;
  238.      int si, di, ds, es;
  239.        } r;
  240. extern int _showds();
  241.  
  242. r.ax = 0x1A00;                    /* DOS interrupt 1A */
  243. r.dx = (char *)dta;
  244. r.ds = _showds();
  245. sysint(0x21, &r, &r);                /* sets data transfer address */
  246.  
  247. r.ax = 0x4E00;                    /* DOS interrupt 4E */
  248. r.cx = mask;
  249. r.dx = path;
  250. r.ds = _showds();
  251. return(!(sysint(0x21, &r, &r) & 1));        /* fills the structure */
  252. }
  253.  
  254. /* find_next - find the next file in the same directory */
  255.  
  256. find_next(dta)
  257. struct dta *dta;
  258. {
  259. struct { int ax, bx, cx;
  260.      char *dx;
  261.      int si, di, ds, es;
  262.        } r;
  263. extern int _showds();
  264.  
  265. r.ax = 0x1A00;
  266. r.dx = (char *)dta;
  267. r.ds = _showds();
  268. sysint(0x21, &r, &r);                /* set dta */
  269.  
  270. r.ax = 0x4F00;
  271. return(!(sysint(0x21, &r, &r) & 1));        /* fill the table */
  272. }
  273.  
  274. /* curdrv - get current default drive */
  275.  
  276. curdrv(sp)
  277. char *sp;
  278. {
  279. struct { int ax, bx, cx;
  280.      char *dx, *si, *di, *ds, *es;
  281.        } r;
  282.  
  283. r.ax = 0x1900;                    /* DOS interrupt 19 */
  284. sysint(0x21, &r, &r);                /* gets current drive number */
  285. *sp++ = r.ax + 'a';                             /* convert to symbolic drive name */
  286. *sp++ = ':';
  287. return;
  288. }
  289.  
  290. /* getpath - get path to directory on indicated drive */
  291.  
  292. getpath(sp)
  293. char *sp;
  294. {
  295. struct { int ax, bx, cx, dx;
  296.      char *si;
  297.      int di, ds, es;
  298.        } r;
  299. extern int _showds();
  300.  
  301. strcat(sp, DQS);            /* append root file symbol to drive name */
  302.  
  303. r.ax = 0x4700;                /* DOS interrupt 47 gets path string */
  304. r.dx = *sp - '`';                       /* convert drive name to index */
  305. r.ds = _showds();
  306. r.si = sp + 3;                /* paste string after root symbol */
  307. sysint(0x21, &r, &r);
  308. return;
  309. }
  310.  
  311. /* getcl - get cluster size & space left on requested drive */
  312.  
  313. getcl(pp)
  314. char *pp;
  315. {
  316. struct { int ax, bx, cx, dx, si, di, ds, es;} r;
  317. int cs;
  318. extern long left;
  319. extern int drive;
  320.  
  321. if(*(pp+1) == ':')                      /* use specified drive if any */
  322.     r.ax = *pp - 'a';
  323. else {
  324.     r.ax = 0x1900;            /* else get code for default drive */
  325.     sysint(0x21, &r, &r);
  326.     }
  327. drive = r.ax & 0x7F;
  328. if(!usage && !sizonly && drive == 2)
  329.     return(HARDCS);
  330. else {
  331.     r.dx = drive + 1;        /* 0 = default, 1 = a, etc */
  332.     r.ax = 0x3600;
  333.     sysint(0x21, &r, &r);        /* DOS interrupt hex 36 */
  334.     if(r.ax == 0xFFFF)        /* gets free disk space */
  335.         return(0);        /* and other goodies */
  336.     else {
  337.         cs = r.ax * r.cx;    /* r.ax = sectors/cluster */
  338.         left = (long)cs * r.bx; /* r.bx = # unused clusters */
  339.         return(cs);        /* r.cx = bytes/sector */
  340.         }            /* r.dx = drive capacity (clusters) */
  341.     }
  342. }
  343.  
  344. /* comp - compare size of two entries */
  345.  
  346. comp(a,b)
  347. struct outbuf *a, *b;
  348. {
  349. int y;
  350.  
  351. if(tsrt) {
  352.     if(a->odate != b->odate)            /* if dates differ */
  353.         y = (a->odate < b->odate) ? -1 : 1;    /* that settles it */
  354.     else
  355.         y = (a->otime < b->otime) ? -1 : 1;    /* else compare times */
  356.     return((rev) ? y : -y);
  357.     }
  358. else {
  359.     y = strcmp(a->oname, b->oname);         /* name comparison */
  360.     return((rev) ? -y : y);
  361.     }
  362. }
  363.  
  364. /* shortlist - print a list of names in 5 columns */
  365.  
  366. shortlist(k)
  367. int k;                    /* total number to print */
  368. {
  369. int i, m, n;
  370.  
  371. if(colm)
  372.     n = k;                /* set for 1-column listing */
  373. else
  374.     n = (k + 4)/5;            /* or 5-column */
  375.  
  376. for(i=0; i < n; i++){
  377.     for(m = 0; (i+m) < k; m += n) {
  378.         if(obuf[i+m].oattr & 0x10)
  379.             strcat(obuf[i+m].oname, DQS);    /* mark directories */
  380.         putname(i+m);                            /* print the name */
  381.         fputs("   ", stdout);
  382.         }
  383.     fputc(endlin(),stdout);
  384.     }
  385. return;
  386. }
  387.  
  388. /* putname - convert name to lower case and print */
  389.  
  390. putname(i)
  391. int i;
  392. {
  393. int c, j = 0;
  394.  
  395. while((c = tolower(obuf[i].oname[j])) != 0) {
  396.     fputc(c, stdout);
  397.     j++;
  398.     }
  399. while(j++ < NAMESIZ - 1)                /* pad to columnarize */
  400.     fputc(' ', stdout);
  401. }
  402.  
  403. /* endlin - end a line and watch for screen overflow */
  404.  
  405. static int lc = 0;                    /* line counter */
  406.  
  407. endlin(fp)
  408. FILE *fp;
  409. {
  410. extern int tsc;                 /* true if output is to screen */
  411. int c;
  412.  
  413. if(tsc && ++lc >= SCRSIZ) {            /* pause if output is to console screen */
  414.     fputs("\n--More--", fp);         /* and we've shown a screenful */
  415.     c = ci();
  416.     fputs("\n", fp);
  417.     switch(c) {
  418.         case '\r':                      /* <RETURN> - show 1 more line */
  419.             lc = SCRSIZ - 1;
  420.             break;
  421.         case 'q':                       /* quit with "q" or "ctrl-C" */
  422.         case '\003':
  423.             exit(0);
  424.         default:
  425.             lc = 0;         /* else show another screenful */
  426.             break;
  427.         }
  428.     return('\b');
  429.     }
  430. else
  431.     return('\n');
  432. }
  433.  
  434. /* longlist - list everything about files in two columns */
  435.  
  436. struct llst {                /* structure to hold file information */
  437.     char *fattr;            /* file attribute pointer */
  438.     long size;            /* file size */
  439.     int day;            /* the day of creation */
  440.     int mnum;            /* month number */
  441.     int yr;
  442.     int hh;             /* creation times */
  443.     int mm;
  444.     int ap;             /* am or pm */
  445.     } l;
  446.  
  447. longlist(k)
  448. int k;                       /* total number to list */
  449. {
  450.  
  451. int i, m, n, cdate;
  452. char *mon, *mname();
  453.  
  454. cdate = gcdate();               /* get current date (in months) */
  455. n = k;                   /* set for 1 column listing */
  456. for(i=0; i < n; i++){
  457.     for(m = 0; (m+i) < k; m += n) {
  458.         fill(i+m, &l);                            /* fill llst structure */
  459.         mon = mname(l.mnum);   /* conv month # to name */
  460.         fprintf(stdout, "%s%7ld  %2d %s ",
  461.             l.fattr, l.size, l.day, mon);
  462.         if(cdate >= (l.yr * 12 +l.mnum) + 12)
  463.             fprintf(stdout, " %4d  ", l.yr);        /* print year if too old */
  464.         else {
  465.             fprintf(stdout, "%2d:%02d%c ",
  466.                 l.hh, l.mm, l.ap);                /* else print time */
  467.             }
  468.         putname(i+m);
  469.         if(m+n < k)
  470.             fputs("\272 ", stdout);     /* double bar separator */
  471.         }
  472.     fputc(endlin(),stdout);
  473.     }
  474. return;
  475. }
  476.  
  477. /* fill - fill long list structure with file information */
  478.  
  479. fill(i, ll)
  480. int i;
  481. struct llst *ll;
  482. {
  483. int j, k;
  484. static char fbuf[16][4] = {
  485.     "--w",
  486.     "---",
  487.     "-hw",
  488.     "-h-",
  489.     "s-w",
  490.     "s--",
  491.     "shw",
  492.     "sh-",
  493.     "d-w",
  494.     "d--",
  495.     "dhw",
  496.     "dh-",
  497.     "d-w",
  498.     "d--",
  499.     "dhw",
  500.     "dh-"
  501.     };
  502.  
  503. if((obuf[i].oattr & 0x10) && obuf[i].oname[0] != '.') {
  504.     ll->size = clsize;
  505.     j = 8;                   /* if directory, use block size */
  506.     }                                    /* and set dir attr offset */
  507. else {
  508.     ll->size = obuf[i].osize;        /* else use file size */
  509.     j = 0;                    /* and file attr offset */
  510.     }
  511. ll->fattr = fbuf[(obuf[i].oattr & 0x07) + j];    /* point to symbolic attr */
  512. ll->day = obuf[i].odate & 0x1F;
  513. ll->mnum = (obuf[i].odate >> 5) & 0x0F;
  514. ll->yr = (obuf[i].odate >> 9) + 1980;
  515. k = obuf[i].otime >> 5;             /* this is a mess */
  516. ll->mm = k & 0x3f;
  517. ll->ap = ((ll->hh = k >> 6) >= 12) ? 'p' : 'a';
  518. if(ll->hh > 12)
  519.     ll->hh -= 12;
  520. if(ll->hh == 0)
  521.     ll->hh = 12;
  522. return;
  523. }
  524.  
  525.  
  526. /* gcdate - get current date (in months) for comparison */
  527.  
  528. gcdate()
  529. {
  530. struct { unsigned int ax, bx, cx, dx, si, di, ds, es;} r;
  531.  
  532.     r.ax = 0x2A00;
  533.     sysint(0x21, &r, &r);
  534.     return(r.cx * 12 + (r.dx >> 8));    /* yr * 12 + month */
  535. }
  536.  
  537. /* mname - convert month number to month name */
  538.  
  539. char *mname(n)
  540. int n;
  541. {
  542. static char *name[] = {
  543.     "???",
  544.     "Jan",
  545.     "Feb",
  546.     "Mar",
  547.     "Apr",
  548.     "May",
  549.     "Jun",
  550.     "Jul",
  551.     "Aug",
  552.     "Sep",
  553.     "Oct",
  554.     "Nov",
  555.     "Dec"
  556.     };
  557. return((n < 1 || n > 12) ? name[0] : name[n]);
  558. }
  559.  
  560. #ifdef CIC86
  561.  
  562. _showds()
  563. {
  564. struct{int cs, ss, ds, es;} r;
  565.  
  566. segread(&r);
  567. return(r.ds);
  568. }
  569.  
  570. ci()
  571. {
  572. return(bdos(7) & 0xFF);
  573. }
  574.  
  575. #endif
  576.